// Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using Microsoft.WindowsAPICodePack.DirectX;
using Microsoft.WindowsAPICodePack.DirectX.Direct3D10;
using Microsoft.WindowsAPICodePack.DirectX.DXGI;
//using Microsoft.WindowsAPICodePack.DirectX.Direct3DX10;
using System.Windows.Media.Media3D;
using System.Runtime.InteropServices;
using System.Reflection;
using System.IO;

namespace Microsoft.WindowsAPICodePack.DirectX.DirectXUtilities
{

    /// <summary>
    /// Manages the XMesh file loading
    /// </summary>
    public class XMeshManager
    {
        internal D3DDevice device;

        internal Effect effect;
        internal EffectTechnique techniqueRenderTexture;
        internal EffectTechnique techniqueRenderVertexColor;
        internal EffectTechnique techniqueRenderMaterialColor;

        internal EffectScalarVariable brightnessVariable;
        internal EffectVectorVariable materialColorVariable;
        internal EffectMatrixVariable worldVariable;
        internal EffectMatrixVariable viewVariable;
        internal EffectMatrixVariable projectionVariable;
        internal EffectShaderResourceVariable diffuseVariable;

        /// <summary>
        /// Creates the mesh manager
        /// </summary>
        /// <param name="device"></param>
        public XMeshManager( D3DDevice device )
        {
            this.device = device;

            // Create the effect
            Stream effectStream = typeof( XMeshManager ).Assembly.GetManifestResourceStream( 
                "Microsoft.WindowsAPICodePack.DirectX.DirectXUtilities.Mesh.MeshLoaders.XMesh.fxo" );
            effect = device.CreateEffectFromCompiledBinary( new BinaryReader( effectStream ) );

            // Obtain the techniques
            techniqueRenderTexture = effect.GetTechniqueByName( "RenderTextured" );
            techniqueRenderVertexColor = effect.GetTechniqueByName( "RenderVertexColor" );
            techniqueRenderMaterialColor = effect.GetTechniqueByName( "RenderMaterialColor" );

            // Obtain the variables
            brightnessVariable = effect.GetVariableByName( "Brightness" ).AsScalar( );
            materialColorVariable = effect.GetVariableByName( "MaterialColor" ).AsVector( );
            worldVariable = effect.GetVariableByName( "World" ).AsMatrix( );
            viewVariable = effect.GetVariableByName( "View" ).AsMatrix( );
            projectionVariable = effect.GetVariableByName( "Projection" ).AsMatrix( );
            diffuseVariable = effect.GetVariableByName( "tex2D" ).AsShaderResource( );
        }

        public void SetViewAndProjection( Matrix3D view, Matrix3D projection )
        {
            viewVariable.SetMatrix( view.ToArray( ) );
            projectionVariable.SetMatrix( projection.ToArray( ) );
        }

        /// <summary>
        /// Returns an XMesh object that contains the data from a specified .X file.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public XMesh Open( string path )
        {
            XMesh mesh = new XMesh();
            mesh.Load( path, this );
            return mesh;
        }

        /// <summary>
        /// Reutrns a specialization of an XMesh object that contains the data from a specified .X file
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path"></param>
        /// <returns></returns>
        public T Open<T>( string path ) where T : XMesh, new()
        {
            T mesh = new T();
            mesh.Load( path, this );
            return mesh;
        }
    }
}
